/**
 * @Description: 路径
 * @Author 卞鹏飞 <228443632@qq.com>
 * @create 18/08/24 11:09 AM
 */
import path from 'node:path'
import { createDefineMock, defineMock } from 'rspack-plugin-mock/helper'
import sfutils2 from 'sf-utils2'

const { isArray, isFunction, isPlainObject, isNoNullable, isValidJSON } = sfutils2

export { Result } from './utils.js'

/**
 * @param {object[]|object} mock
 */
export const defineAPIMock = createDefineMock((mock) => {
  const upperMethods = (method) => {
    method ||= ''
    return method
      .split(',')
      .filter(Boolean)
      .map((v) => v.trim().toUpperCase())
  }

  const transformMock = (mockItem, key) => {
    const defaultMethod = ['POST', 'GET']
    if (isFunction(mockItem)) {
      const [method, tempUrl] = (key || '').split(' ').filter(Boolean)
      return {
        url: path.join('/mock/', tempUrl),
        method: upperMethods(method || defaultMethod),
        response: function (req, res) {
          const originEnd = res.end.bind(res)
          res.end = function () {
            const [$0, ...rest] = [...(arguments || [])]
            // if (isPlainObject($0) || isArray($0)) {
            //   return res.end(JSON.stringify($0), ...rest)
            // }
            if (isValidJSON($0)) {
              return originEnd($0, ...rest)
            }
            return originEnd(JSON.stringify($0), ...rest)
          }

          const result = mockItem.apply(this, arguments)
          if (isNoNullable(result)) {
            // 不为空 不是undefined或者null
            return res.end(result)
          }
        }
      }
    }

    if (isPlainObject(mockItem)) {
      // 普通对象

      if (!mockItem.url) {
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        const [_, tempUrl] = (key || '').split(' ').filter(Boolean)
        mockItem.url = path.join('/mock/', tempUrl)
      } else {
        mockItem.url = path.join('/mock/', mockItem.url)
      }

      if (!mockItem.method) {
        const [method, _] = (key || '').split(' ').filter(Boolean)
        mockItem.method = method
      }

      mockItem.method ||= defaultMethod
      mockItem.method = upperMethods(mockItem.method)

      return mockItem
    }
    return undefined
  }

  if (isArray(mock)) {
    return defineMock(mock.map((mockItem) => transformMock(mockItem)).filter(Boolean))
  }

  if (isPlainObject(mock)) {
    return defineMock(
      Object.entries(mock)
        .map(([key, mockItem]) => transformMock(mockItem, key))
        .filter(Boolean)
    )
  }

  return []
})
